package com.lobov.utils.yale;

import com.lobov.entities.ContainerOfSnipsYale;
import com.lobov.entities.yale.MatrixYale;
import com.lobov.entities.yale.SnipYale;

/**
 * 
 * Утилита для резки йельских матриц по количеству процессоров
 */

public class CutterYale {
	/**
	 * горизонтальная резка матрицы
	 * 
	 * @param matrix
	 *            подаваемая на разкройку матрица
	 * @param numOfProcessors
	 *            количество обрабатываемых процессоров
	 * @return возвращает контейнер лоскутов ContainerOfSnips
	 * @throws Exception
	 */
	public static ContainerOfSnipsYale cutMatrixHorizontal(MatrixYale matrix,
			int numOfProcessors) throws Exception {
		// if (matrix.isCompressed()){
		// throw new Exception("Нельзя разрезать сжатую матрицу");
		// }
		ContainerOfSnipsYale containerOfSnips = new ContainerOfSnipsYale(
				numOfProcessors, matrix.getXlength());
		// наполняем контейнер лоскутами (учитываем что номер лоскута совпадает
		// с номером процессора)
		for (int i = 0; i < numOfProcessors; i++) {
			containerOfSnips.setSnipByIndex(
					getSnipFromMatrixYale(matrix, numOfProcessors, i), i);
		}
		return containerOfSnips;
	}

	private static SnipYale getSnipFromMatrixYale(MatrixYale matrix,
			int numOfProcessors, int num_of_snip) throws Exception {
		// в случае если это последний лоскут и он  больше
		if (num_of_snip == numOfProcessors - 1
				&& matrix.getYlength() % numOfProcessors > 0) {
			int num_of_start_vector = num_of_snip
					* (matrix.getYlength() / numOfProcessors);
			int num_of_end_vector = num_of_start_vector + matrix.getYlength()
					/ numOfProcessors + matrix.getYlength() % numOfProcessors - 1;
			SnipYale snip = new SnipYale(matrix.getXlength(),
										num_of_end_vector - num_of_start_vector + 1,
										num_of_snip);
			int position = 0;
			for (int i = num_of_start_vector; i <= num_of_end_vector; i++) {
				snip.addVector(matrix.getVector(i), position);
				position ++;
			}
			return snip;
			// если все лоскуты равны
		} else {
			int num_of_start_vector = num_of_snip
					* (matrix.getYlength() / numOfProcessors);
			int num_of_end_vector = num_of_start_vector + matrix.getYlength()
					/ numOfProcessors - 1;
			SnipYale snip = new SnipYale(matrix.getXlength(),
										num_of_end_vector - num_of_start_vector + 1,
										num_of_snip);
			int position = 0;
			for (int i = num_of_start_vector; i <= num_of_end_vector; i++) {
				snip.addVector(matrix.getVector(i), position);
				position ++;
			}
			return snip;
		}
	}

}
